﻿// Copyright 2012 Jack Bulan (agentgeo)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Globalization;

using GemWorkshop.Formats.Nitro;

namespace GemWorkshop.Text
{
    public partial class TextEditor : Form
    {
        private Narc nReader;
        private bool isVar;

        // Info
        private int messages = 0;
        private ushort originalKey;

        public TextEditor()
        {
            InitializeComponent();
            //tabControl1.TabPages.Clear();
            //AddTab("Welcome", "Select a file to start...");

            // Load Narc. :D
            nReader = new Narc(Form1.GameDirectory + "\\" + Form1.GameSettings.ReadValue(Form1.Game, "MessageData"));
            for (int i = 0; i < nReader.FileCount; i++)
            {
                listFiles.Items.Add(string.Format("File {0}", i));
            }

            bSave.Enabled = true;
        }

        private void bSave_Click(object sender, EventArgs e)
        {
            // Save changes
            List<string> msgs = new List<string>();
            for (int i = 0; i < messages; i++)
            {
                msgs.Add(dataGridView1.Rows[i].Cells[2].Value.ToString());
                //MessageBox.Show(dataGridView1.Rows[i].Cells[1].Value.ToString());
            }
            CodeText(msgs.ToArray());
        }

        private void bCross_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void listFiles_SelectedIndexChanged(object sender, EventArgs e)
        {
            // Load the message file.
            try
            {
                this.Cursor = Cursors.WaitCursor;
                Application.DoEvents();
                sText[] texts = DecodeText();

                //dataGridView1.Rows.Clear();
                dataGridView1.Columns.Clear();

                DataTable table = new DataTable("Texts");
                var col1 = table.Columns.Add("Number");
                col1.ReadOnly = true;
                table.Columns.Add("Length").ReadOnly = true;
                table.Columns.Add("Text");
                
                
                int i = 1;
                foreach (sText t in texts)
                {
                    //AddTab("Message " + i, t.Text);
                    var row = table.NewRow();
                    row["Number"] = i.ToString();
                    row["Length"] = t.Size; //+ "/" + t.Size;
                    row["Text"] = t.Text;
                    table.Rows.Add(row);
                    i++;
                }
                dataGridView1.DataSource = table;

                this.Cursor = Cursors.Default;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message+"\n\n" + ex.StackTrace);
            }
        }

        private sText[] DecodeText()
        {
            BinaryReader reader =
                new BinaryReader(
                    nReader.ExtractStream((uint)listFiles.SelectedIndex));

            short len = reader.ReadInt16();
            messages = len; // For later
            //prBar.Maximum = len;
            originalKey = reader.ReadUInt16();
            int x = (int)originalKey * 765 & (int)ushort.MaxValue;

            List<sText> tList = new List<sText>();
            ArrayList aList = new ArrayList();
            List<int> iList = new List<int>();
            sText text;

            //console.Text = "";
            for (int i = 0; i < len; i++)
            {
                // Start, get encoding key.
                text = new sText();
                text.Key2 = x * (i + 1) & (int)ushort.MaxValue;
                text.RealKey = text.Key2 | text.Key2 << 16;
                // Read the offset
                int off = reader.ReadInt32();
                text.StartOffset = off ^ text.RealKey;
                aList.Add(off);
                // Read the size
                int size = reader.ReadInt32();
                text.Size = size ^ text.RealKey;
                iList.Add(size);
                // Add
                tList.Add(text);
                //console.Text += "Message " + i + " Offset: " + off.ToString("X") + "\nMessage " + i + " Length: " + size.ToString("X") + " - " + text.Size.ToString("X") + "\n";
            }

            //console.Text += "\n";
            for (int i = 0; i < len; i++)
            {
                //console.Text += "Message " + i + "\n";
                text = tList[i];

                int y = 596947 * (i + 1) & (int)ushort.MaxValue;
                int z = 0;
                //bool isVar = false;
                StringBuilder sb = new StringBuilder();

                for (int n = 0; n < text.Size; n++)
                {
                    if (z == 4)
                    {
                        isVar = false;
                        //sb.Append(" ");
                        z = 0;
                    }

                    ushort u = reader.ReadUInt16();
                    string chr = GetChar(u ^ y);
                    //console.Text += u.ToString("X4") + " ";
                    if (chr == "[]") // We found a variable!
                    {
                        isVar = true;
                        sb.Append("\\v");
                    }
                    else
                        sb.Append(chr);

                    if (isVar)
                    {
                        z++;
                    }
                    y = y + 18749 & (int)ushort.MaxValue;
                }

                text.Text = sb.ToString();
                //prBar.Value = i;
                tList[i] = text;
                //console.Text += "\n\n";
            }
            //prBar.Value = len;
            return tList.ToArray();
        }

        private string GetChar(int val)
        {
            switch (val)
            {
                case 9660:
                    return "\\r";
                case 9661:
                    return "\\v";
                case 57344:
                    return "\\n";
                case 65534:
                    return "[]"; // We use it to stand for var
                case (int)ushort.MaxValue:
                    return "\\x";
                case 0:
                    return "\\h0000";
                case 1:
                    return "\\h0001";
                case 162:
                    return "0";
                case 163:
                    return "1";
                case 164:
                    return "2";
                case 165:
                    return "3";
                case 166:
                    return "4";
                case 167:
                    return "5";
                case 168:
                    return "6";
                case 169:
                    return "7";
                case 170:
                    return "8";
                case 171:
                    return "9";
                case 172:
                    return "A";
                case 173:
                    return "B";
                case 174:
                    return "C";
                case 175:
                    return "D";
                case 176:
                    return "E";
                case 177:
                    return "F";
                case 178:
                    return "G";
                case 179:
                    return "H";
                case 180:
                    return "I";
                case 181:
                    return "J";
                case 182:
                    return "K";
                case 183:
                    return "L";
                case 184:
                    return "M";
                case 185:
                    return "N";
                case 186:
                    return "O";
                case 187:
                    return "P";
                case 188:
                    return "Q";
                case 189:
                    return "R";
                case 190:
                    return "S";
                case 191:
                    return "T";
                case 192:
                    return "U";
                case 193:
                    return "V";
                case 194:
                    return "W";
                case 195:
                    return "X";
                case 196:
                    return "Y";
                case 197:
                    return "Z";
                case 198:
                    return "a";
                case 199:
                    return "b";
                case 200:
                    return "c";
                case 201:
                    return "d";
                case 202:
                    return "e";
                case 203:
                    return "f";
                case 204:
                    return "g";
                case 205:
                    return "h";
                case 206:
                    return "i";
                case 207:
                    return "j";
                case 208:
                    return "k";
                case 209:
                    return "l";
                case 210:
                    return "m";
                case 211:
                    return "n";
                case 212:
                    return "o";
                case 213:
                    return "p";
                case 214:
                    return "q";
                case 215:
                    return "r";
                case 216:
                    return "s";
                case 217:
                    return "t";
                case 218:
                    return "u";
                case 219:
                    return "v";
                case 220:
                    return "w";
                case 221:
                    return "x";
                case 222:
                    return "y";
                case 223:
                    return "z";
                case 256:
                    if (this.isVar)
                        return "0100";
                    else
                        break;
                case 257:
                    if (this.isVar)
                        return "0101";
                    else
                        break;
                case 259:
                    if (this.isVar)
                        return "0103";
                    else
                        break;
                case 260:
                    if (this.isVar)
                        return "0104";
                    else
                        break;
                case 262:
                    if (this.isVar)
                        return "0106";
                    else
                        break;
                case 263:
                    if (this.isVar)
                        return "0107";
                    else
                        break;
                case 264:
                    if (this.isVar)
                        return "0108";
                    else
                        break;
                case 266:
                    if (this.isVar)
                        return "010A";
                    else
                        break;
                case 270:
                    if (this.isVar)
                        return "010E";
                    else
                        break;
                case 280:
                    if (this.isVar)
                        return "0118";
                    else
                        break;
                case 287:
                    if (this.isVar)
                        return "011F";
                    else
                        break;
                case 289:
                    return "0";
                case 290:
                    return "1";
                case 291:
                    return "2";
                case 292:
                    return "3";
                case 293:
                    return "4";
                case 294:
                    return "5";
                case 295:
                    return "6";
                case 296:
                    return "7";
                case 297:
                    return "8";
                case 298:
                    return "9";
                case 299:
                    return "A";
                case 300:
                    return "B";
                case 301:
                    return "C";
                case 302:
                    return "D";
                case 303:
                    return "E";
                case 304:
                    return "F";
                case 305:
                    return "G";
                case 306:
                    return this.isVar ? "0132" : "H";
                case 307:
                    return this.isVar ? "0133" : "I";
                case 308:
                    return this.isVar ? "0134" : "J";
                case 309:
                    return this.isVar ? "0135" : "K";
                case 310:
                    return "L";
                case 311:
                    return this.isVar ? "0137" : "M";
                case 312:
                    return "N";
                case 313:
                    return "O";
                case 314:
                    return "P";
                case 315:
                    return "Q";
                case 316:
                    return "R";
                case 317:
                    return "S";
                case 318:
                    return "T";
                case 319:
                    return "U";
                case 320:
                    return "V";
                case 321:
                    return "W";
                case 322:
                    return "X";
                case 323:
                    return "Y";
                case 324:
                    return "Z";
                case 325:
                    return "a";
                case 326:
                    return "b";
                case 327:
                    return "c";
                case 328:
                    return "d";
                case 329:
                    return "e";
                case 330:
                    return "f";
                case 331:
                    return "g";
                case 332:
                    return "h";
                case 333:
                    return "i";
                case 334:
                    return "j";
                case 335:
                    return "k";
                case 336:
                    return "l";
                case 337:
                    return "m";
                case 338:
                    return "n";
                case 339:
                    return "o";
                case 340:
                    return "p";
                case 341:
                    return "q";
                case 342:
                    return "r";
                case 343:
                    return "s";
                case 344:
                    return "t";
                case 345:
                    return "u";
                case 346:
                    return "v";
                case 347:
                    return "w";
                case 348:
                    return "x";
                case 349:
                    return "y";
                case 350:
                    return "z";
                case 351:
                    return "À";
                case 352:
                    return "Á";
                case 353:
                    return "Â";
                case 354:
                    return "T";
                case 355:
                    return "Ä";
                case 356:
                    return "T";
                case 357:
                    return "t";
                case 358:
                    return "Ç";
                case 359:
                    return "È";
                case 360:
                    return "É";
                case 361:
                    return "Ê";
                case 362:
                    return "Ë";
                case 363:
                    return "Ì";
                case 364:
                    return "Í";
                case 365:
                    return "Î";
                case 366:
                    return "Ï";
                case 367:
                    return "u";
                case 368:
                    return "Ñ";
                case 369:
                    return "Ò";
                case 370:
                    return "Ó";
                case 371:
                    return "Ô";
                case 372:
                    return "W";
                case 373:
                    return "Ö";
                case 374:
                    return "×";
                case 375:
                    return "y";
                case 376:
                    return "Ù";
                case 377:
                    return "Ú";
                case 378:
                    return "Û";
                case 379:
                    return "Ü";
                case 380:
                    return "z";
                case 381:
                    return "Ž";
                case 382:
                    return "ß";
                case 383:
                    return "à";
                case 384:
                    return "á";
                case 385:
                    return "â";
                case 386:
                    return "?";
                case 387:
                    return "ä";
                case 388:
                    return "?";
                case 389:
                    return "?";
                case 390:
                    return "ç";
                case 391:
                    return "è";
                case 392:
                    return "é";
                case 393:
                    return "ê";
                case 394:
                    return "ë";
                case 395:
                    return "ì";
                case 396:
                    return "í";
                case 397:
                    return "î";
                case 398:
                    return "ï";
                //case 399:
                //    return "?";
                case 400:
                    return "ñ";
                case 401:
                    return "ò";
                case 402:
                    return "ó";
                case 403:
                    return "ô";
                case 404:
                    return "?";
                case 405:
                    return "ö";
                case 406:
                    return "÷";
                case 407:
                    return "I";
                case 408:
                    return "ù";
                case 409:
                    return "ú";
                case 410:
                    return "û";
                case 411:
                    return "ü";
                case 412:
                    return "?";
                case 413:
                    return "?";
                case 414:
                    return "?";
                case 415:
                    return "Œ";
                case 416:
                    return "œ";
                case 417:
                    return "o";
                case 418:
                    return "?";
                case 419:
                    return "ª";
                case 420:
                    return "º";
                case 421:
                    return "\x1D49\x02B3";
                case 422:
                    return "\x02B3\x1D49";
                case 423:
                    return "\x02B3";
                case 424:
                    return "¥";
                case 425:
                    return "¡";
                case 426:
                    return "¿";
                case 427:
                    return "!";
                //case 428:
                //    return "?";
                case 429:
                    return ",";
                case 430:
                    return ".";
                case 431:
                    return "...";
                case 432:
                    return "·";
                case 433:
                    return "/";
                case 434:
                    return "‘";
                case 435:
                    return "'";
                case 436:
                    return "\"";
                case 437:
                    return "\"";
                case 438:
                    return "„";
                case 439:
                    return "«";
                case 440:
                    return "»";
                case 441:
                    return "(";
                case 442:
                    return ")";
                case 443:
                    return "?";
                case 444:
                    return "?";
                case 445:
                    return "+";
                case 446:
                    return "-";
                case 447:
                    return "*";
                case 448:
                    return "#";
                case 449:
                    return "=";
                case 450:
                    return "&";
                case 451:
                    return "~";
                case 452:
                    return ":";
                case 453:
                    return ";";
                case 454:
                    return "„";
                case 455:
                    return "«";
                case 456:
                    return "»";
                case 457:
                    return "(";
                case 458:
                    return ")";
                //case 459:
                //    return "?";
                //case 460:
                //    return "?";
                case 461:
                    return "+";
                case 462:
                    return "-";
                case 463:
                    return "*";
                case 466:
                    return "%";
                case 478:
                    return " ";
                case 515:
                    if (this.isVar)
                        return "0203";
                    else
                        break;
            }
            return this.isVar ? "" : "\\h" + val.ToString("X4");
        }

        /* private void CodeTextOld(string[] messageLine)
        {
            BinaryWriter writer = new BinaryWriter(nReader.ExtractStream((uint)listFiles.SelectedIndex));
            writer.Write((short)messages); // Number of messages
            writer.Write((short)this.originalKey);
            int num2 = this.originalKey * 765 & (int)ushort.MaxValue;
            int num3 = 0;
            for (int index = 0; index < messages; ++index)
            {
                int num4 = num2 * (index + 1) & (int)ushort.MaxValue;
                int num5 = num4 | num4 << 16;
                if (index == 0)
                {
                    int num6 = 8 * messages + 4 ^ num5;
                    writer.Write(num6);
                }
                else
                {
                    num3 += this.GetActualSize(messageLine[index - 1]) * 2;
                    int num6 = 8 * messages + 4 + num3 ^ num5;
                    writer.Write(num6);
                }
                int num7 = (int)(short)this.GetActualSize(messageLine[index]) ^ num5;
                writer.Write(num7);
            }
            for (int index1 = 0; index1 < messages; ++index1)
            {
                int num4 = 596947 * (index1 + 1) & (int)ushort.MaxValue;
                char[] chArray = messageLine[index1].ToCharArray();
                bool flag = false;
                for (int startIndex = 0; startIndex < chArray.Length - 1; ++startIndex)
                {
                    if (!flag)
                    {
                        int index2 = startIndex + 8;
                        while ((int)chArray[index2] != 32)
                            ++index2;
                        startIndex = index2 + 2;
                        flag = true;
                    }
                    else
                    {
                        char ch = chArray[startIndex];
                        switch (ch)
                        {
                            /*case '[':
                                int index2 = startIndex;
                                while ((int)chArray[index2] != 93)
                                    ++index2;
                                int num5 = index2 + 1;
                                string[] strArray = messageLine[index1].Substring(startIndex, num5 + 1 - startIndex).Split(new char[1]
                {
                  ' '
                });
                                writer.Write((short)(0xFFFE ^ num4));
                                int num6 = num4 + 18749 & (int)ushort.MaxValue;
                                writer.Write((short)(GetValue(strArray[1].ToString()) ^ num6));
                                int num7 = num6 + 18749 & (int)ushort.MaxValue;
                                writer.Write((short)(GetValue(strArray[2].ToString()) ^ num7));
                                int num8 = num7 + 18749 & (int)ushort.MaxValue;
                                writer.Write((short)(GetValue(strArray[3].ToString()) ^ num8));
                                num4 = num8 + 18749 & (int)ushort.MaxValue;
                                startIndex = num5;
                                break; *
                            case '\\':
                                {
                                    char type = chArray[startIndex + 1];
                                    if (type != 'h' && type != 'v')
                                    {
                                        writer.Write((short)(GetValue(ch.ToString() + chArray[startIndex + 1].ToString()) ^ num4));
                                        num4 = num4 + 18749 & (int)ushort.MaxValue;
                                    }
                                    else if (type == 'h')
                                    {
                                        writer.Write((short)(GetValue(ch.ToString() + chArray[startIndex + 1].ToString()) ^ num4));
                                        num4 = num4 + 18749 & (int)ushort.MaxValue;
                                    }
                                    else // Var
                                    {
                                        int index2 = startIndex;
                                        while ((int)chArray[index2] != 93)
                                            ++index2;
                                        int num5 = index2 + 1;
                                        string[] strArray = messageLine[index1].Substring(startIndex, num5 + 1 - startIndex).Split(new char[1]
                {
                  ' '
                });
                                        writer.Write((short)(0xFFFE ^ num4));
                                        int num6 = num4 + 18749 & (int)ushort.MaxValue;
                                        writer.Write((short)(GetValue(strArray[1].ToString()) ^ num6));
                                        int num7 = num6 + 18749 & (int)ushort.MaxValue;
                                        writer.Write((short)(GetValue(strArray[2].ToString()) ^ num7));
                                        int num8 = num7 + 18749 & (int)ushort.MaxValue;
                                        writer.Write((short)(GetValue(strArray[3].ToString()) ^ num8));
                                        num4 = num8 + 18749 & (int)ushort.MaxValue;
                                        startIndex = num5;
                                    }
                                    ++startIndex;
                                }
                                break;
                            default:
                                writer.Write((this.GetValue(ch.ToString()) ^ num4));
                                num4 = num4 + 18749 & (int)ushort.MaxValue;
                                break;
                        }
                    }
                }
            }
        } */

        private void CodeText(string[] messageLines)
        {
            // Parse the text into write-able parts
            //console.Text = "";
            List<ushort>[] msgs = ParseText(messageLines);

            // Now encode and write
            // ...
            BinaryWriter bw = new BinaryWriter(nReader.ExtractStream((uint)listFiles.SelectedIndex));
            
            // Guess (and set) the length...
            int lenGuess = 4 + (messageLines.Length * 8);
            foreach (List<ushort> l in msgs) lenGuess += (l.Count * 2);
            if (lenGuess > bw.BaseStream.Length) bw = new BinaryWriter(new MemoryStream(new byte[lenGuess]));

            // Write the header
            bw.Write((short)messages); // Number of messages
            bw.Write(originalKey); // The encoding key
            int x = originalKey * 765 & ushort.MaxValue;
            // Format: [offset] [size] -- both int32
            int pos = 0;
            for (int i = 0; i < messages; i++)
            {
                int len = msgs[i].Count;
                int key2 = x * (i + 1) & ushort.MaxValue;
                int realKey = key2 | key2 << 16;

                if (i == 0)
                {
                    int offset = 8 * messages + 4 ^ realKey;
                    bw.Write(offset); // Offset for message 0
                    //console.Text += "Message " + i + " Offset: " + offset.ToString("X");
                }
                else // Offsets for the rest
                {
                    pos += len * 2; // Length of decoded
                    int offset = 8 * messages + 4 + pos ^ realKey;
                    bw.Write(offset);
                    //console.Text += "Message " + i + " Offset: " + offset.ToString("X");
                }
                int cLen = len ^ realKey;
                bw.Write(cLen);
                //console.Text += "\nMessage " + i + " Length: " + cLen.ToString("X") + " - " + len.ToString("X") + "\n";
            }
            //console.Text += "\n";

            // Write encoded characters
            for (int i = 0; i < messages; i++)
            {
                //console.Text += "Message " + i + "\n";
                int key = 596947 * (i + 1) & ushort.MaxValue;
                foreach (ushort c in msgs[i])
                {
                    //console.Text += (c ^ key).ToString("X4") + " ";
                    bw.Write((ushort)(c ^ key));
                    key = key + 18749 & ushort.MaxValue;
                }
                //console.Text += "\n\n";
            }

            /* int index = 1;
            foreach (List<ushort> vals in msgs)
            {
                console.Text += "Message " + index + "Uncoded\n";
                foreach (ushort u in vals)
                {
                    console.Text += u.ToString("X4") + " ";
                }
                console.Text += "\n\n";
            } */

            nReader.ReplaceFile((uint)listFiles.SelectedIndex, (MemoryStream)bw.BaseStream);

            bw.Close();
            bw.Dispose();
        }

        private List<ushort>[] ParseText(string[] messageLines)
        {
            // Break up the text
            List<ushort>[] msgs = new List<ushort>[messageLines.Length];
            for (int j = 0; j < messageLines.Length; j++)
            {
                string line = messageLines[j];
                List<ushort> chars = new List<ushort>();
                for (int i = 0; i < line.Length; i++) // :D
                {
                    char c = line[i];
                    if (c == '\\')
                    {
                        c = line[i + 1];
                        if (c == 'h') // Hex
                        {
                            // Hex character format: \h0000
                            // Get two characters
                            ushort val = ushort.Parse(line[i + 2].ToString() + line[i + 3] + line[i + 4] + line[i + 5], NumberStyles.HexNumber);
                            chars.Add(val);
                            i += 6;
                            //MessageBox.Show("Next: " + line[i]);
                        }
                        else if (c == 'v') // Variable
                        {
                            // Add controller
                            //MessageBox.Show("Variable: " + "\\v" + line[i + 2].ToString() + line[i + 3] + line[i + 4] + line[i + 5] + "\\h" + line[i + 8].ToString() + line[i + 9] + line[i + 10] + line[i + 11] + "\\h" + line[i + 14].ToString() + line[i + 15] + line[i + 16] + line[i + 17]);
                            chars.Add(0xFFFE); // Variable controller
                            ushort v1 = ushort.Parse(line[i + 2].ToString() + line[i + 3] + line[i + 4] + line[i + 5], NumberStyles.HexNumber); // Var. #
                            ushort p1 = ushort.Parse(line[i + 8].ToString() + line[i + 9] + line[i + 10] + line[i + 11], NumberStyles.HexNumber); // Param. 1
                            ushort p2 = ushort.Parse(line[i + 14].ToString() + line[i + 15] + line[i + 16] + line[i + 17], NumberStyles.HexNumber); // Param. 2
                            chars.Add(v1);
                            chars.Add(p1);
                            chars.Add(p2);
                            i += 17;
                            //MessageBox.Show("Next: " + line[i]);
                        }
                        else // Other (\n, \r, \x, ...)
                        {
                            //MessageBox.Show("\\" + c);
                            ushort val = GetValue("\\" + c); // Control
                            chars.Add(val);
                            i += 1;
                            //MessageBox.Show("Next: " + line[i]);
                        }
                    }
                    else // Normal character
                    {
                        ushort val = GetValue(c.ToString());
                        chars.Add(val); // :D
                    }
                }
                msgs[j] = chars;
            }
            return msgs;
        }

        /* public int GetActualSize(string p)
        {
            int num = 0;
            bool flag = false;
            p.ToCharArray();
            for (int index1 = 0; index1 < p.Length - 1; ++index1)
            {
                char ch = p[index1];
                if (!flag)
                {
                    int index2 = index1 + 8;
                    while ((int)p[index2] != 32)
                        ++index2;
                    index1 = index2 + 2;
                    flag = true;
                }
                else if ((int)ch == 91)
                {
                    while ((int)p[index1] != 93)
                        ++index1;
                    num += 3;
                }
                else if ((int)ch == 47)
                {
                    ++num;
                    ++index1;
                }
                else
                    ++num;
            }
            return num;
        } */

        public ushort GetValue(string p)
        {
            switch (p)
            {
                case "0000":
                    return 0;
                case "0001":
                    return 1;
                /* case "0":
                    return 162;
                case "1":
                    return 163;
                case "2":
                    return 164;
                case "3":
                    return 165;
                case "4":
                    return 166;
                case "5":
                    return 167;
                case "6":
                    return 168;
                case "7":
                    return 169;
                case "8":
                    return 170;
                case "9":
                    return 171;
                case "A":
                    return 172;
                case "B":
                    return 173;
                case "C":
                    return 174;
                case "D":
                    return 175;
                case "E":
                    return 176;
                case "F":
                    return 177;
                case "G":
                    return 178;
                case "H":
                    return 179;
                case "I":
                    return 180;
                case "J":
                    return 181;
                case "K":
                    return 182;
                case "L":
                    return 183;
                case "M":
                    return 184;
                case "N":
                    return 185;
                case "O":
                    return 186;
                case "P":
                    return 187;
                case "Q":
                    return 188;
                case "R":
                    return 189;
                case "S":
                    return 190;
                case "T":
                    return 191;
                case "U":
                    return 192;
                case "V":
                    return 193;
                case "W":
                    return 194;
                case "X":
                    return 195;
                case "Y":
                    return 196;
                case "Z":
                    return 197;
                case "a":
                    return 198;
                case "b":
                    return 199;
                case "c":
                    return 200;
                case "d":
                    return 201;
                case "e":
                    return 202;
                case "f":
                    return 203;
                case "g":
                    return 204;
                case "h":
                    return 205;
                case "i":
                    return 206;
                case "j":
                    return 207;
                case "k":
                    return 208;
                case "l":
                    return 209;
                case "m":
                    return 210;
                case "n":
                    return 211;
                case "o":
                    return 212;
                case "p":
                    return 213;
                case "q":
                    return 214;
                case "r":
                    return 215;
                case "s":
                    return 216;
                case "t":
                    return 217;
                case "u":
                    return 218;
                case "v":
                    return 219;
                case "w":
                    return 220;
                case "x":
                    return 221;
                case "y":
                    return 222;
                case "z":
                    return 223; */
                case "POKE:":
                    return 256;
                case "POKE2:":
                    return 257;
                case "NAME:":
                    return 259;
                case "PLACE:":
                    return 260;
                case "MOVE:":
                    return 262;
                case "NAT:":
                    return 263;
                case "ITEM:":
                    return 264;
                case "POFFIN ITEM:":
                    return 266;
                case "TRAINER:":
                    return 270;
                case "KEY ITEM:":
                    return 280;
                case "ACC.:":
                    return 287;
                case "0":
                    return 289;
                case "1":
                    return 290;
                case "2":
                    return 291;
                case "3":
                    return 292;
                case "4":
                    return 293;
                case "5":
                    return 294;
                case "6":
                    return 295;
                case "7":
                    return 296;
                case "8":
                    return 297;
                case "9":
                    return 298;
                case "A":
                    return 299;
                case "B":
                    return 300;
                case "C":
                    return 301;
                case "D":
                    return 302;
                case "E":
                    return 303;
                case "F":
                    return 304;
                case "G":
                    return 305;
                case "NUM:":
                    return 306;
                case "H":
                    return 306;
                case "LEVEL:":
                    return 307;
                case "I":
                    return 307;
                case "NUM2:":
                    return 308;
                case "J":
                    return 308;
                case "NUM3:":
                    return 309;
                case "K":
                    return 309;
                case "L":
                    return 310;
                case "MONEY:":
                    return 311;
                case "M":
                    return 311;
                case "N":
                    return 312;
                case "O":
                    return 313;
                case "P":
                    return 314;
                case "Q":
                    return 315;
                case "R":
                    return 316;
                case "S":
                    return 317;
                case "T":
                    return 318;
                case "U":
                    return 319;
                case "V":
                    return 320;
                case "W":
                    return 321;
                case "X":
                    return 322;
                case "Y":
                    return 323;
                case "Z":
                    return 324;
                case "a":
                    return 325;
                case "b":
                    return 326;
                case "c":
                    return 327;
                case "d":
                    return 328;
                case "e":
                    return 329;
                case "f":
                    return 330;
                case "g":
                    return 331;
                case "h":
                    return 332;
                case "i":
                    return 333;
                case "j":
                    return 334;
                case "k":
                    return 335;
                case "l":
                    return 336;
                case "m":
                    return 337;
                case "n":
                    return 338;
                case "o":
                    return 339;
                case "p":
                    return 340;
                case "q":
                    return 341;
                case "r":
                    return 342;
                case "s":
                    return 343;
                case "t":
                    return 344;
                case "u":
                    return 345;
                case "v":
                    return 346;
                case "w":
                    return 347;
                case "x":
                    return 348;
                case "y":
                    return 349;
                case "z":
                    return 350;
                case "À":
                    return 351;
                case "Á":
                    return 352;
                case "Â":
                    return 353;
                case "T\x0001":
                    return 354;
                case "Ä":
                    return 355;
                //case "T\x0001":
                //    return 356;
                case "t\x0001":
                    return 357;
                case "Ç":
                    return 358;
                case "È":
                    return 359;
                case "É":
                    return 360;
                case "Ê":
                    return 361;
                case "Ë":
                    return 362;
                case "Ì":
                    return 363;
                case "Í":
                    return 364;
                case "Î":
                    return 365;
                case "Ï":
                    return 366;
                case "u\x0001":
                    return 367;
                case "Ñ":
                    return 368;
                case "Ò":
                    return 369;
                case "Ó":
                    return 370;
                case "Ô":
                    return 371;
                //case "W":
                //    return 372;
                case "Ö":
                    return 373;
                case "×":
                    return 374;
                case "y\x0001":
                    return 375;
                case "Ù":
                    return 376;
                case "Ú":
                    return 377;
                case "Û":
                    return 378;
                case "Ü":
                    return 379;
                case "z\x0001":
                    return 380;
                case "Ž\x0001":
                    return 381;
                case "ß":
                    return 382;
                case "à":
                    return 383;
                case "á":
                    return 384;
                case "â":
                    return 385;
                case "?\x0001":
                    return 386;
                case "ä":
                    return 387;
                //case "?\x0001":
                //    return 388;
                //case "?":
                //    return 389;
                case "ç":
                    return 390;
                case "è":
                    return 391;
                case "é":
                    return 392;
                case "ê":
                    return 393;
                case "ë":
                    return 394;
                case "ì":
                    return 395;
                case "í":
                    return 396;
                case "î":
                    return 397;
                case "ï":
                    return 398;
                case "?\x008F\x0001":
                    return 399;
                case "ñ":
                    return 400;
                case "ò":
                    return 401;
                case "ó":
                    return 402;
                case "ô":
                    return 403;
                //case "?":
                //    return 404;
                case "ö":
                    return 405;
                case "÷":
                    return 406;
                case "I\x0001":
                    return 407;
                case "ù":
                    return 408;
                case "ú":
                    return 409;
                case "û":
                    return 410;
                case "ü":
                    return 411;
                //case "?\x0001":
                //    return 412;
                //case "?\x0001":
                //    return 414;
                case "Œ\x0001":
                    return 415;
                case "œ\x0001":
                    return 416;
                case "o\x0001":
                    return 417;
                //case "?\x0001":
                //    return 418;
                case "ª":
                    return 419;
                case "º":
                    return 420;
                case "\x1D49\x02B3":
                    return 421;
                case "\x02B3\x1D49":
                    return 422;
                case "\x02B3":
                    return 423;
                case "¥":
                    return 424;
                case "¡":
                    return 425;
                case "¿":
                    return 426;
                case "!":
                    return 427;
                case "?":
                    return 428;
                case ",":
                    return 429;
                case ".":
                    return 430;
                case "...":
                    return 431;
                case "·":
                    return 432;
                case "/":
                    return 433;
                case "‘":
                    return 434;
                case "'":
                    return 435;
                case "“":
                    return 436;
                case "”":
                    return 437;
                case "„":
                    return 438;
                case "«":
                    return 439;
                case "»":
                    return 440;
                case "(":
                    return 441;
                case ")":
                    return 442;
                //case "?":
                //    return 443;
                //case "?":
                //    return 444;
                case "+":
                    return 445;
                case "-":
                    return 446;
                case "*":
                    return 447;
                case "#":
                    return 448;
                case "=":
                    return 449;
                case "&":
                    return 450;
                case "~":
                    return 451;
                case ":":
                    return 452;
                case ";":
                    return 453;
                //case "?":
                //    return 454;
                //case "?":
                //    return 455;
                //case "?":
                //    return 456;
                //case "?":
                //    return 457;
                //case "?":
                //    return 458;
                //case "?":
                //    return 459;
                //case "?":
                //    return 460;
                //case "?":
                //    return 461;
                //case "?":
                //    return 462;
                //case "?":
                //    return 463;
                case "%":
                    return 466;
                case " ":
                    return 478;
                case "COLOR:":
                    return 515;
                case "\\n":
                    return 57344;
                case "\\r":
                    return 9660;
                case "\\v":
                    return 9661;
                case "[]":
                    return 65534;
                case "\\x":
                    return (int)ushort.MaxValue;
                default:
                    return 0;
            }
        }

        public struct sText
        {
            public int Id;
            public int StartOffset;
            public string Text;
            public int Key2;
            public int RealKey;
            public int Size;
        }

        private void dataGridView1_KeyDown(object sender, KeyEventArgs e)
        {
            
        }
    }
}
